// 防抖
// 1. 触发事件,函数n秒后才执行,
// 2. n秒内又执行,重新开始计时

// 前端中频繁触发的事件
// 1. window 的 resize、scroll
// 2. mousedown、mousemove
// 3. keyup、keydown

// func中this指向dom元素
// debounce中this指向windows
// event 对象
// func对象有返回值
function debounce(func, wait) {
  let timeout, result;
  
  return function () {
    const context = this;
    const args = arguments;

    clearTimeout(timeout);
    timeout = setTimeout(function () {
      result = func.apply(context, args);
    }, wait);

    return result;
  };
}

// 增加需求
// 立即执行
function debounce(func, wait) {
  var timeout, result;
  var calledImmediately = false;

  return function () {
    var context = this;
    var args = arguments;

    if(immediate && !calledImmediately){
      result = func.apply(context, args);
      calledImmediately = true
    }

    clearTimeout(timeout);
    timeout = setTimeout(function () {
      if(!immediate || calledImmediately){
        result = func.apply(context, args);
        // calledImmediately = false 重置标志以便于下次调用时立即执行（如果需要）
      }
    }, wait);

    return result;
  };
}

// 立即执行2
function debounce(func, wait, immediate) {

  var timeout, result;

  return function () {
      var context = this;
      var args = arguments;

      if (timeout) clearTimeout(timeout);
      if (immediate) {
          // 如果已经执行过，不再执行
          var callNow = !timeout;
          timeout = setTimeout(function(){
              timeout = null;
          }, wait)
          if (callNow) result = func.apply(context, args)
      }
      else {
          timeout = setTimeout(function(){
              result = func.apply(context, args)
          }, wait);
      }

      return result;
  }
}

// 可以取消
function debounce(func, wait) {
  var timeout, result;
  var calledImmediately = false;

  var debounced = function () {
    var context = this;
    var args = arguments;

    if(immediate && !calledImmediately){
      result = func.apply(context, args);
      calledImmediately = true
    }

    clearTimeout(timeout);
    timeout = setTimeout(function () {
      if(!immediate || calledImmediately){
        result = func.apply(context, args);
        // calledImmediately = false 重置标志以便于下次调用时立即执行（如果需要）
      }
    }, wait);

    return result;
  };

  debounced.cancel = function(){
    clearTimeout(timeout)
    timeout = null
  }

  return debounced
}
